
package com.yifeng.util;

import com.mysql.cj.jdbc.AbandonedConnectionCleanupThread;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

/**
 * JDBC 资源清理监听器：在 Web 应用销毁时主动释放 MySQL 驱动相关资源，防止内存泄漏
 */
@WebListener
public class JdbcCleanupListener implements ServletContextListener {

    /*
    负责人：

    功能：Web 应用启动时的初始化回调方法（本监听器无需初始化操作，留空）

    参数：servletContextEvent - ServletContext 事件对象，包含应用上下文信息

    返回值：无
    */
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        // 无需执行任何操作
    }

    /*
    负责人：

    功能：Web 应用停止或重新部署时的销毁回调方法。
          主要执行两项清理操作：
          1. 关闭 MySQL Connector/J 内部的 abandoned connection cleanup 线程；
          2. 注销当前 Web 应用注册的所有 JDBC 驱动实例。
          目的是防止 Tomcat 报出 clearReferencesJdbc 和 clearReferencesThreads 内存泄漏警告。

    参数：sce - ServletContext 事件对象，包含应用上下文信息

    返回值：无
    */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // 1. 关闭 MySQL 的 abandoned connection cleanup 线程
        try {
            AbandonedConnectionCleanupThread.checkedShutdown();
        } catch (Exception e) {
            // 忽略异常，避免影响应用正常关闭流程
        }

        // 2. 注销所有由当前应用注册的 JDBC 驱动
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            try {
                DriverManager.deregisterDriver(driver);
            } catch (SQLException e) {
                // 忽略异常，避免影响其他驱动的注销
            }
        }
    }
}